﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows;
using System.Windows.Input;
using System.Windows.Data;
using BAL.EstRec.FDVIndicador;
using BAL.EstRec;

namespace Nav3.PGrid
{
    public delegate void EventHandler<CellAddedEventArgs>(object sender, CellAddedEventArgs e);

    public class PGrid
    {
        public Grid _leftGrdHeader;
        public Grid _rightGrdHeader;
        public Grid _leftGrdData;
        public Grid _rightGrdData;
        private List<PGridColData> frzCols;
        private List<IPGridRowHeader> hds;
        public int colWidth;
        public int colFreezeWith;
        public bool IsEditEnable;
        private GridLength rowHeight;

        public ColumnDefinitionCollection getLeftHeaderColumnDef()
        {
            return this._leftGrdHeader.ColumnDefinitions;
        }

        public ColumnDefinitionCollection getLeftDataColumnDef()
        {
            return this._leftGrdData.ColumnDefinitions;
        }        


        private List<string> rowInnerMap;
        private PGridColData colInnerMap;
        private int frezzeColCount;
        private Border pastEditBorder;

        private bool isOutEditing;

        public event EventHandler<CellAddedEventArgs> CellAdded;
        public virtual void OnCellAdded(CellAddedEventArgs e)
        {
            if (CellAdded != null)
                CellAdded(this, e);
        }

        public event EventHandler<CellAddedEventArgs> ColumnRowSubHeaderAdded;
        public virtual void OnColumnRowSubHeaderAdded(CellAddedEventArgs e)
        {
            if (ColumnRowSubHeaderAdded != null)
                ColumnRowSubHeaderAdded(this, e);
        }

        public event EventHandler<CellAddedEventArgs> ColumnRowHeaderAdded;
        public virtual void OnColumnRowHeaderAdded(CellAddedEventArgs e)
        {
            if (ColumnRowHeaderAdded != null)
                ColumnRowHeaderAdded(this, e);
        }

        public event EventHandler<CellAddedEventArgs> CellEdited;
        public virtual void OnCellEdited(CellAddedEventArgs e)
        {
            if(CellEdited != null)
                CellEdited(this, e);
        }//


        public PGrid(Grid leftGrdHeader, Grid leftGrdData, Grid rightGrdHeader, Grid rightGrdData)
        {
            this._leftGrdHeader = leftGrdHeader;
            this._rightGrdHeader = rightGrdHeader;
            this._leftGrdData = leftGrdData;
            this._rightGrdData = rightGrdData;

            this.rowInnerMap=new List<string>();
            this.frezzeColCount = 0;

            this.colFreezeWith = 110;//180;   //2012-12-11   170;//
            this.colWidth = 110;   // 170;//
            this.isOutEditing = false;
            this.rowHeight = new GridLength(22);
            this.IsEditEnable = true;
        }

        public void addColumnFrezze(string colName,List<string> data,bool isTheKey)
        {
            if (this.frzCols == null)
                this.frzCols = new List<PGridColData>();

            this.frzCols.Add(new PGridColData(colName, data,isTheKey,this.colFreezeWith));
        }
        public void addColumnFrezze(string colName, List<string> data, bool isTheKey,int width)
        {
            if (this.frzCols == null)
                this.frzCols = new List<PGridColData>();

            this.frzCols.Add(new PGridColData(colName, data, isTheKey, width));
        }

        public void defineRowHeader(List<IPGridRowHeader> hds)
        {
            this.hds = hds;
        }

        public void addRowHeaderData(IPGridRowHeader rh)
        {
            if (this.hds == null)
                this.hds = new List<IPGridRowHeader>();

            this.hds.Add(rh);
        }

        private void generateFreezeColHeader(string colTitle,int width)
        {
            int rowCount = 0;

            if (this._leftGrdHeader.RowDefinitions.Count <= 0)
            {
                //Agregar fila para espacio
                this._leftGrdHeader.RowDefinitions.Add(new RowDefinition() { Height=this.rowHeight });
                rowCount++;

                //Agregar fila para el titulo del encabezado
                this._leftGrdHeader.RowDefinitions.Add(new RowDefinition() { Height = this.rowHeight });
                rowCount++;
            }
            
            //Agregar la columna
            this._leftGrdHeader.ColumnDefinitions.Add(new ColumnDefinition() { Width=new GridLength( width) });

            //Asignar el titulo de la columna
            Border brd = this.createReadCell(colTitle);

            //Agregar al grid
            Grid.SetColumn(brd,this.frezzeColCount);
            Grid.SetRow(brd,1);
            this._leftGrdHeader.Children.Add(brd);
        }

        private void generateFreezeColData(PGridColData p)
        {
            int rowCount = 0;
            Border brd;

            this.generateFreezeColHeader(p.colName,p.width);

            this._leftGrdData.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(p.width) });
            this._leftGrdData.RowDefinitions.Add(new RowDefinition() { Height = this.rowHeight });

            //Ciclo para agregar filas
            foreach (string colData in p.colValues)
            {
                //Agregar fila sino existe
                if (rowCount>=this._leftGrdData.RowDefinitions.Count)
                {
                    this._leftGrdData.RowDefinitions.Add(new RowDefinition() { Height = this.rowHeight });
                }

                //Generar celda
                brd = this.createReadCell(colData);

                //Agregar al grid
                Grid.SetColumn(brd, this.frezzeColCount);
                Grid.SetRow(brd, rowCount);
                this._leftGrdData.Children.Add(brd);

                //Incrementar contador de filas
                rowCount++;
            }

            this.frezzeColCount++;
        }

        public void generateFreezeCols()
        {
            foreach(PGridColData p in this.frzCols)
            {
                if (p.isTheKey)
                    this.colInnerMap = p;

                this.generateFreezeColData(p);
            }
        }

        public void generateRowHeader()
        {
            //Crear el row header
            int col=0;
            int addedCols = 0;
            this._rightGrdHeader.RowDefinitions.Add(new RowDefinition() { Height = this.rowHeight });
            this._rightGrdHeader.RowDefinitions.Add(new RowDefinition() { Height = this.rowHeight });

            foreach (IPGridRowHeader rh in this.hds)
            {
                foreach (string subHeader in rh.SubHeaders)
                {
                    this._rightGrdHeader.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(this.colFreezeWith) });

                    Border brdSubHeader = this.createReadCell(subHeader);
                    Grid.SetRow(brdSubHeader, 1);
                    Grid.SetColumn(brdSubHeader, col);

                    this._rightGrdHeader.Children.Add(brdSubHeader);

                    this.rowInnerMap.Add(subHeader);

                    this.OnColumnRowSubHeaderAdded(new CellAddedEventArgs("", subHeader, (object)brdSubHeader));

                    addedCols++;
                    col++;
                }

                Border brdTopHeader = this.createReadCell(rh.TopHeaderName);

                Grid.SetRow(brdTopHeader, 0);
                Grid.SetColumn(brdTopHeader, col-addedCols);
                Grid.SetColumnSpan(brdTopHeader, addedCols);

                this.OnColumnRowHeaderAdded(new CellAddedEventArgs("", rh.TopHeaderName, (object)brdTopHeader));

                this._rightGrdHeader.Children.Add(brdTopHeader);

                addedCols = 0;
            }
        }

        public void generateRowData()
        {
            Border brd = null ;
            int colCount=0;
            int rowCount=0;
            Thickness leftTopTh = new Thickness(0.5, 0.5, 0, 0);
            Thickness leftRightTopTh = new Thickness(0.5, 0.5, 0.5, 0);
            

            foreach (string col in this.colInnerMap.colValues)
            {
                this._rightGrdData.RowDefinitions.Add(new RowDefinition() { Height = this.rowHeight });
                colCount = 0;
                if (col == this.colInnerMap.colValues.Last())
                {
                    leftTopTh.Bottom = 0.5;
                }

                foreach (string row in this.rowInnerMap)
                {
                    if (this._rightGrdData.ColumnDefinitions.Count<this.rowInnerMap.Count)
                        this._rightGrdData.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(this.colWidth) });

                    if (this.IsEditEnable)
                    {
                        brd = this.createEditCell("", col, row);
                        brd.GotFocus += delegate(object sender, RoutedEventArgs e)
                        {
                            if (!this.isOutEditing)
                            {
                                if (this.pastEditBorder != null)
                                {
                                    this.pastEditBorder.BorderBrush = Brushes.Silver;
                                    ((StackPanel)this.pastEditBorder.Child).Children[0].Visibility = Visibility.Visible;
                                    ((StackPanel)this.pastEditBorder.Child).Children[1].Visibility = Visibility.Collapsed;
                                }

                                ((Border)sender).BorderBrush = Brushes.Blue;
                                ((StackPanel)((Border)sender).Child).Children[0].Visibility = Visibility.Collapsed;
                                ((StackPanel)((Border)sender).Child).Children[1].Visibility = Visibility.Visible;
                                this.pastEditBorder = ((Border)sender);
                                FocusManager.SetFocusedElement(brd, ((TextBox)((StackPanel)((Border)sender).Child).Children[1]));
                                Keyboard.Focus(((TextBox)((StackPanel)((Border)sender).Child).Children[1]));
                            }
                            else
                            {
                                this.isOutEditing = false;
                            }

                        };
                        brd.MouseUp += delegate(object sender, MouseButtonEventArgs e)
                        {
                            ((Border)sender).Focus();
                        };
                    }
                    else
                    {
                        brd = this.createReadCell("");
                    }

                    brd.Focusable = true;
                    brd.Background = Brushes.Transparent;
                    brd.IsHitTestVisible = true;
                    brd.BorderThickness = leftTopTh;
                    Grid.SetColumn(brd, colCount);
                    Grid.SetRow(brd, rowCount);
                    this._rightGrdData.Children.Add(brd);

                    this.OnCellAdded(new CellAddedEventArgs(col, row, brd));

                    colCount++;
                }
                if (col == this.colInnerMap.colValues.Last())
                {
                    leftRightTopTh.Bottom = 0.5;
                    brd.BorderThickness = leftRightTopTh;
                    leftRightTopTh.Bottom = 0;
                }
                else
                {
                    brd.BorderThickness = leftRightTopTh;
                }
                
                rowCount++;
            }
        }

        private Border createReadCell(string text)
        {
            Border brdSubHeader = new Border();
            brdSubHeader.BorderThickness = new System.Windows.Thickness(0.5);
            brdSubHeader.BorderBrush = Brushes.Gray;
            brdSubHeader.Focusable = true;
            brdSubHeader.IsHitTestVisible = true;

            TextBlock txtBlock = new TextBlock();
            txtBlock.Text = text;

            txtBlock.HorizontalAlignment = HorizontalAlignment.Stretch;

            brdSubHeader.Child = txtBlock;
            
            return brdSubHeader;
        }

        private Border createEditCell(string text,string col,string row)
        {
            Border brdSubHeader = new Border();
            brdSubHeader.BorderThickness = new System.Windows.Thickness(1);
            brdSubHeader.BorderBrush = Brushes.Gray;

            StackPanel sp = new StackPanel();

            TextBlock txtBlock = new TextBlock();
            txtBlock.Text = text;
            txtBlock.HorizontalAlignment = HorizontalAlignment.Center;

            TextBox txtBox = new TextBox();
            txtBox.Text = text;
            txtBox.HorizontalAlignment = HorizontalAlignment.Center;
            txtBox.Visibility = Visibility.Collapsed;
            txtBox.Width = this.colWidth-5;
            txtBox.Height = this.rowHeight.Value;
            txtBox.KeyUp += delegate(object sender, KeyEventArgs e)
            {
                if (e.Key == Key.Enter)
                {
                    //guardar
                    txtBox.Visibility = Visibility.Collapsed;
                    txtBlock.Visibility = Visibility.Visible;
                    
                    
                    this.isOutEditing = true;
                    
                }
                else if (e.Key == Key.Escape)
                {
                    //Salir
                    txtBox.Visibility = Visibility.Collapsed;
                    txtBlock.Visibility = Visibility.Visible;
                    this.isOutEditing = true;
                }
            };

            string _col = col;
            string _row = row;

            txtBox.SourceUpdated += delegate(object sender, DataTransferEventArgs e)
            {
                BindingExpression be = txtBlock.GetBindingExpression(TextBlock.TextProperty);
                Binding parentBinding = be.ParentBinding;
                this.OnCellEdited(new CellAddedEventArgs(_col,_row, (object)brdSubHeader));
            };

            sp.Children.Add(txtBlock);
            sp.Children.Add(txtBox);

            brdSubHeader.Child = sp;

            return brdSubHeader;
        }
    }

    public class CellAddedEventArgs : System.EventArgs
    {
        public string col;
        public string row;
        public object tb;

        public CellAddedEventArgs(string col, string row, object tb)
        {
            this.col = col;
            this.row = row;
            this.tb = tb;
        }
    }//end class

    public class PGridColData
    {
        public string colName;
        public List<string> colValues;
        public bool isTheKey;
        public int width;

        public PGridColData(string colName,List<string> colValues)
        {
            this.colName = colName;
            this.colValues = colValues;
            this.isTheKey = false;
        }
        public PGridColData(string colName, List<string> colValues,bool isTheKey,int width)
        {
            this.colName = colName;
            this.colValues = colValues;
            this.isTheKey = isTheKey;
            this.width = width;
        }
    }

}
